#include <cassert>
#include <cstdlib>
#include <iostream>
#include <vector>
#include "ourhdr.h"

using std::vector;

#define TEST

using std::cout;
using std::cerr;
using std::cin;
using std::endl;

#ifdef TEST
static void testPos(){
	Pos p1;
	Pos p2(10, 10);
	//Pos p3(10, 60);
	Pos p4(p2);
	Pos p5(10, 11);
	Pos p6(10, 9);
	Pos p7(9, 10);
	Pos p8(11, 10);
	assert(p2 == p4);
	assert(p1.row() == 0 && p1.col() == 0);

	assert(!p1.nextTo(p2));
	assert(p2.nextTo(p5));
	assert(p2.nextTo(p6));
	assert(p2.nextTo(p7));
	assert(p2.nextTo(p8));

	assert(p2.isAboveOf(p8));
	assert(!p2.isBelowOf(p8));
	assert(!p2.isOnTheLeftOf(p8));
	assert(!p2.isOnTheRightOf(p8));
	assert(p2.isBelowOf(p7));
	assert(p2.isOnTheLeftOf(p5));
	assert(p2.isOnTheRightOf(p6));

	assert(p2.upper() == p7);
	assert(p2.lower() == p8);
	assert(p2.left()  == p6);
	assert(p2.right() == p5);
	
	p4.setRow(11);
	assert(p2.nextTo(p4));
	p4.setCol(11);
	assert(!p2.nextTo(p4));

	cout << "class Pos works successfully!\n";
	system("sleep 2");
}

static void testPixel(){
	Pixel p1(0, 0, '*'), p2(Pixel::max_row-1, Pixel::max_col-1);
	assert(p1.row() == 0 && p1.col() == 0 && p1.character() == '*');
	p1.setRow(Pixel::max_row/2);
	p1.setCol(Pixel::max_col/2);
	p1.setCharacter('@');
	assert(p1.row() == Pixel::max_row/2 && p1.col() == Pixel::max_col/2 && p1.character() == '@');
	std::cout << "class Pixel works successfully!\n";
	system("sleep 2");
}


static void testObject(){
	Pixel p1(0, 0, '*');
	Pixel p2(1, 1, '!');
	Pixel p3(2, 2, '@');
	Object o1, o2;
	Screen s1;

	assert(!o1.hasPos(0, 0));
	o1.addBack(p1);
	assert(o1.hasPos(0, 0));
	assert(o1.first().pos() == Pos(0,0));
	o1.delBack();
	assert(!o1.hasPos(0, 0));
	o1.addFront(p1);
	assert(o1.hasPos(0, 0));
	o1.delFront();
	assert(!o1.hasPos(0, 0));

	o1.addFront(p1);
	o1.addFront(p2);
	o2.addBack(p1);
	o2.addFront(p3);
	assert(o1.overlapWith(o2));

	o1.castTo(s1);
	s1.show();
	
	std::cout << "Class Object works successfully!\n";
	system("sleep 2");
}

static void testScreen(){
	Screen s1;

	s1.show();
	system("sleep 5");
	s1.setPixel(0, 0, '*');
	s1.setPixel(1, 1, '!');
	s1.setWords(15, "Hello world!");
	assert(s1.getPixel(0, 0) == '*');
	assert(s1.getPixel(1, 1) == '!');
	s1.show();

	std::cout << "Class Screen works successfully!\n";
	system("sleep 2");
}

static void testSnake(){
	Snake snake;
	Screen screen;

	screen.clear();
	snake.castTo(screen);
	screen.show();
	while(1){
		char c = getchar();
		if(c == 'q')
			break;
		switch(c){
			case 'a':
				snake.move(snake.head().pos().left(),LEFT);
				break;
			case 'w':
				snake.move(snake.head().pos().upper(),UP);
				break;
			case 's':
				snake.move(snake.head().pos().lower(),DOWN);
				break;
			case 'd':
				snake.move(snake.head().pos().right(), RIGHT);
				break;
			default:
				break;
		}
		screen.clear();
		snake.castTo(screen);
		screen.show();
		std::cout << "Now the head is " << snake.head() << std::endl;
	}

	std::cout << "Class Snake works successfully!\n";
	system("sleep 2");
}

static void testFood(){
	Food food;
	Screen screen;
	vector<Pos> poses;

	screen.clear();
	food.castTo(screen);
	screen.show();
	system("sleep 2");

	poses.push_back(Pos(10,0));
	poses.push_back(Pos(10,1));
	poses.push_back(Pos(10,2));
	poses.push_back(Pos(20,0));
	poses.push_back(Pos(20,1));
	poses.push_back(Pos(20,2));

	food.setValue(10);
	assert(food.value() == 10);

	while(1){
		char c = getchar();
		if(c == 'q') break;
		food.regen(poses);
		screen.clear();
		food.castTo(screen);
		screen.show();
		system("sleep 2");
	}

	std::cout << "Class Food works successfully!\n";
	system("sleep 2");
}

static void testGame(){
	Game thisgame;
	thisgame.exec();
}

static void test(){
	//testPos();
	//testPixel();
	//testObject();
	//testScreen();
	//testSnake();
	//testFood();
	testGame();
}

#endif

int main(){
#ifdef TEST
	test();
#endif
	return 0;
}
